package com.fjwt.gz.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.fjwt.gz.core.constants.ApiCodeEnum;
import com.fjwt.gz.core.constants.Constants;
import com.fjwt.gz.core.exception.BizException;
import com.fjwt.gz.core.third.interfaces.IOfficialService;
import com.fjwt.gz.core.utils.SpringBeansUtil;
import com.fjwt.gz.core.utils.WxUtil;
import com.fjwt.gz.db.base.BaseAgentApp;
import com.fjwt.gz.db.bo.ActivityAwardAndSettingBo;
import com.fjwt.gz.db.bo.CouponResultBo;
import com.fjwt.gz.db.entity.ActivityAppEntity;
import com.fjwt.gz.db.entity.AgentInfoEntity;
import com.fjwt.gz.db.entity.AwardAgentEntity;
import com.fjwt.gz.db.entity.AwardCouponEntity;
import com.fjwt.gz.db.entity.AwardGoodsEntity;
import com.fjwt.gz.db.entity.AwardScoreEntity;
import com.fjwt.gz.db.entity.FansAwardEntity;
import com.fjwt.gz.db.entity.FansPayEntity;
import com.fjwt.gz.db.entity.FansUserEntity;
import com.fjwt.gz.db.entity.OnlyOneAwardEntity;
import com.fjwt.gz.db.entity.PayAuthEntity;
import com.fjwt.gz.db.entity.ScoreRecordTotalEntity;
import com.fjwt.gz.db.vo.AgentEmployeeVO;
import com.fjwt.gz.interfaces.ISendCouponService;
import com.fjwt.gz.service.wx.WxCouponsServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

/**
 * 发送奖品统一service
 **/
@Slf4j
@Service
public class SendAwardService {

    @Value("${isFormal.code}")
    private boolean isFormalCode;

    @Autowired
    private ActivityAwardService activityAwardService;
    @Autowired
    private AwardCouponService awardCouponService;
    @Autowired
    private AwardSettingService awardSettingService;
    @Autowired
    private WxCouponsServiceImpl wxCouponsService;
    @Autowired
    private PayAuthService payAuthService;
    @Autowired
    private AwardGoodsService awardGoodsService;
    @Autowired
    private ScoreRecordTotalService scoreRecordTotalService;
    @Autowired
    private FansAwardService fansAwardService;
    @Autowired
    private FansPayService fansPayService;
    @Autowired
    private AgentAppService agentAppService;
    @Autowired
    private AwardAgentService awardAgentService;
    @Autowired
    private AwardScoreService awardScoreService;
    @Autowired
    private IOfficialService officialService;
    @Autowired
    private OfficialMenuService officialMenuService;
    @Autowired
    private ActivityAppService activityAppService;
    @Autowired
    private FansUserService fansUserService;
    @Autowired
    private OnlyOneAwardService onlyOneAwardService;

    /**
     * 发放卡券/实物
     */
    public Long sendCouponOrGoods(Long fansId, String appId, ActivityAwardAndSettingBo activityAwardAndSettingBo, Long payAuthId, Long activityChannelId, boolean isReduceNum, String extJson) {
        return sendAward(fansId, appId, activityAwardAndSettingBo, payAuthId, activityChannelId, isReduceNum, extJson, null, null, null);
    }

    /**
     * 发放积分
     */
    public Long sendScore(Long fansId, String appId, ActivityAwardAndSettingBo activityAwardAndSettingBo, Long activityChannelId, boolean isReduceNum, String agentNo, Long infoId, String infoType) {
        return sendAward(fansId, appId, activityAwardAndSettingBo, null, activityChannelId, isReduceNum, null, agentNo, infoId, infoType);
    }

    /**
     * 发放奖品且增加获奖记录
     * @param fansId
     * @param appId
     * @param activityAwardAndSettingBo
     * @param payAuthId
     * @param activityChannelId
     * @param isReduceNum
     * @param extJson
     * @param agentNo 发放机构
     * @param infoId 发放积分所需参数(其他类型可传空)
     * @param infoType 发放积分所需参数(其他类型可传空)
     */
    private Long sendAward(Long fansId, String appId, ActivityAwardAndSettingBo activityAwardAndSettingBo, Long payAuthId, Long activityChannelId, boolean isReduceNum,
                           String extJson, String agentNo, Long infoId, String infoType) {
        log.info("增加获奖记录进来的参数fansId：{},activityAwardAndSettingBo:{},payAuthId:{}", fansId, JSONUtil.toJsonStr(activityAwardAndSettingBo), payAuthId);

        // 构建获奖记录参数
        FansAwardEntity fansAwardEntity = new FansAwardEntity();
        fansAwardEntity.setFansId(fansId);
        fansAwardEntity.setAppId(appId);
        fansAwardEntity.setAwardId(activityAwardAndSettingBo.getAwardId());
        fansAwardEntity.setAwardType(activityAwardAndSettingBo.getAwardType());
        fansAwardEntity.setActivityChannelId(activityChannelId);
        if (Constants.AWARD.GOODS == activityAwardAndSettingBo.getAwardType()) {
            fansAwardEntity.setState(Constants.FANS_AWARD_STATE.ACTIVATE);
        } else {
            fansAwardEntity.setState(Constants.FANS_AWARD_STATE.UNUSED);
        }
        fansAwardEntity.setRemark(activityAwardAndSettingBo.getRemark());
        if (StringUtils.isNotEmpty(extJson)) {
            fansAwardEntity.setExtraJson(extJson);
        }
        Integer scoreValue = send(fansAwardEntity, payAuthId, isReduceNum, extJson, activityAwardAndSettingBo, agentNo, infoId, infoType);
        if (Constants.AWARD.SCORE == activityAwardAndSettingBo.getAwardType()) {
            return Long.valueOf(scoreValue);
        }
        fansAwardService.save(fansAwardEntity);
        log.info("用户发放的奖品数据：{}", JSONUtil.toJsonStr(fansAwardEntity));
        return fansAwardEntity.getFansAwardId();
    }

    /**
     * 发放奖品
     * @param fansAwardEntity
     * @param payAuthId
     * @param isReduceNum
     * @param extJson
     * @param activityAwardAndSettingBo
     * @param agentNo 发放积分所需参数(其他类型可传空)
     * @param infoId 发放积分所需参数(其他类型可传空)
     * @param infoType 发放积分所需参数(其他类型可传空)
     */
    private Integer send(FansAwardEntity fansAwardEntity, Long payAuthId, boolean isReduceNum, String extJson, ActivityAwardAndSettingBo activityAwardAndSettingBo, String agentNo, Long infoId, String infoType) {
        //先减库存后放奖品，以免产生并发
        Object successAwardEntity = null;
        if (isReduceNum) {
            successAwardEntity = activityAwardService.reduceNum(fansAwardEntity.getAwardId(), fansAwardEntity.getAwardType());
            if (successAwardEntity == null) {
                throw new BizException("当前奖品已无库存");
            }
        }
        if (Constants.AWARD.COUPON == fansAwardEntity.getAwardType()) {
            AwardCouponEntity awardCouponEntity = null;
            if (isReduceNum) {
                awardCouponEntity = (AwardCouponEntity) successAwardEntity;
            } else {
                awardCouponEntity = awardCouponService.getById(fansAwardEntity.getAwardId());
                if (awardCouponEntity == null) {
                    throw new BizException("当前奖品不存在");
                }
            }
            //校验是否回执，如果是添加回执信息，改变回执状态
            awardSettingService.checkIsRecipt(activityAwardAndSettingBo, extJson, fansAwardEntity);
            fansAwardEntity.setOverTime(getWechatCouponOverTime(awardCouponEntity.getEndTime(), awardCouponEntity.getAvailableDays()));
            CouponResultBo couponResultBo = sendWechatCoupon(fansAwardEntity.getFansId(), payAuthId, awardCouponEntity);
            fansAwardEntity.setCouponThirdId(couponResultBo.getCouponThirdId());
        } else if (Constants.AWARD.GOODS == fansAwardEntity.getAwardType()) {
            AwardGoodsEntity awardGoodsEntity = null;
            if (isReduceNum) {
                awardGoodsEntity = (AwardGoodsEntity) successAwardEntity;
            } else {
                awardGoodsEntity = awardGoodsService.getById(fansAwardEntity.getAwardId());
                if (awardGoodsEntity == null) {
                    throw new BizException("当前奖品不存在");
                }
            }
            fansAwardEntity.setOverTime(awardGoodsEntity.getGoodsOverTime());
        } else if (Constants.AWARD.SCORE == fansAwardEntity.getAwardType()) {
            AwardScoreEntity awardScoreEntity = null;
            if (isReduceNum) {
                awardScoreEntity = (AwardScoreEntity) successAwardEntity;
            } else {
                awardScoreEntity = awardScoreService.getById(fansAwardEntity.getAwardId());
                if (awardScoreEntity == null) {
                    throw new BizException("当前奖品不存在");
                }
            }
            fansAwardEntity.setOverTime(scoreRecordTotalService.getScoreOverTime(awardScoreEntity.getOverDays(), awardScoreEntity.getOverType(), awardScoreEntity.getOverTime()));
            ScoreRecordTotalEntity scoreRecordTotalEntity = new ScoreRecordTotalEntity();
            scoreRecordTotalEntity.setFansId(fansAwardEntity.getFansId());
            scoreRecordTotalEntity.setAppId(fansAwardEntity.getAppId());
            scoreRecordTotalEntity.setInfoId(infoId);
            scoreRecordTotalEntity.setInfoType(infoType);
            scoreRecordTotalEntity.setName(awardScoreEntity.getScoreName());
            scoreRecordTotalEntity.setScore(awardScoreEntity.getScoreValue());
            scoreRecordTotalEntity.setFlag(Constants.SCORE_FLAG.ADD);
            scoreRecordTotalEntity.setActivityId(activityAwardAndSettingBo.getActivityId());
            if (fansAwardEntity.getActivityChannelId() != null) {
                scoreRecordTotalEntity.setActivityChannelId(fansAwardEntity.getActivityChannelId());
            }
            scoreRecordTotalService.addScoreRecordTotal(agentNo, scoreRecordTotalEntity, awardScoreEntity.getOverDays(), awardScoreEntity.getOverType(), awardScoreEntity.getOverTime());
            return awardScoreEntity.getScoreValue();
        } else {
            fansAwardEntity.setOverTime(activityAwardAndSettingBo.getEndTime());
        }
        return null;
    }

    /**
     * 获取微信卡券过期时间
     *
     * @param overTime      微信卡券活动结束时间
     * @param availableDays 领取后n天失效（当天过期，并非24小时）
     * @return
     */
    private Date getWechatCouponOverTime(Date overTime, Integer availableDays) {
        log.info("计算卡券真正过期时间overTime：{},availableDays：{}", overTime, availableDays);
        Date realOverTime = null;
        if (null != availableDays && 0 != availableDays) {
            DateTime dateTime = DateUtil.endOfDay(DateUtil.offsetDay(new Date(), availableDays - 1));
            if (dateTime.isAfter(overTime)) {
                realOverTime = overTime;
            } else {
                realOverTime = dateTime;
            }
        } else {
            realOverTime = overTime;
        }
        log.info("计算后的卡券真正过期时间：{}", realOverTime);
        return realOverTime;
    }

    /**
     * 微信发券
     */
    private CouponResultBo sendWechatCoupon(Long fansId, Long payAuthId, AwardCouponEntity awardCouponEntity) {
        CouponResultBo couponResultBo = null;
        if (payAuthId == null) {
            couponResultBo = wxCouponsService.sendCoupons(awardCouponEntity, fansId);
        } else {
            PayAuthEntity payAuthEntity = payAuthService.getById(payAuthId);
            String ifCode = payAuthEntity.getIfCode();
            //            二鑫--同主体发券测试，不合并至任一分支 ---------start
            if ("wx".equals(ifCode)) {
                couponResultBo = wxCouponsService.sendCoupons(awardCouponEntity, fansId);
            } else {
                //            二鑫--同主体发券测试，不合并至任一分支 ---------end
                ISendCouponService sendCouponService = SpringBeansUtil.getBean(ifCode + "SendCouponService", ISendCouponService.class);
                if (ObjectUtils.isEmpty(sendCouponService)){
                    throw new BizException("网络异常，请稍候重试！");
                }
                couponResultBo = sendCouponService.couponSend(payAuthEntity, fansId, awardCouponEntity.getPayConfig(), awardCouponEntity.getCouponId());
            }
        }
        if (couponResultBo != null) {
            log.info("出资方发放微信卡券成功后返回信息：{}", JSONUtil.toJsonStr(couponResultBo));
            return couponResultBo;
        } else {
            throw new BizException("微信发放卡券异常！");
        }
    }

    /**
     * 发放待激活的奖品
     *
     * @param fansId            用户ID
     * @param appId             appid
     * @param awardId           奖品ID
     * @param awardType         奖品类型
     * @param activityEndTime   过期时间（活动结束日期）
     * @param remark            备注
     * @param activityChannelId 渠道码ID
     * @param tag               类别标签
     * @param extraJson         额外的附加数据（如：模版编号：{“templateNo”:"ACTE001"}）
     */
    @Transactional
    public long sendActivateAward(Long fansId, String appId, Long awardId, Integer awardType, Date activityEndTime, String remark, Long activityChannelId, String tag, String extraJson, AgentInfoEntity agentInfoEntity) {
        FansAwardEntity fansAwardEntity = new FansAwardEntity();
        fansAwardEntity.setFansId(fansId);
        fansAwardEntity.setAppId(appId);
        fansAwardEntity.setAwardId(awardId);
        fansAwardEntity.setAwardType(awardType);
        fansAwardEntity.setOverTime(activityEndTime);
        fansAwardEntity.setState(Constants.FANS_AWARD_STATE.ACTIVATE);
        fansAwardEntity.setRemark(remark);
        fansAwardEntity.setExtraJson(extraJson);
        fansAwardEntity.setActivityChannelId(activityChannelId);
        fansAwardService.save(fansAwardEntity);
        if (Constants.FANS_AWARD_TAG.REAL_NAME_AUTH.equals(tag)) {
            OnlyOneAwardEntity onlyOneAwardEntity = new OnlyOneAwardEntity();
            onlyOneAwardEntity.setFansAwardId(fansAwardEntity.getFansAwardId());
            onlyOneAwardEntity.setFansId(fansId);
            onlyOneAwardEntity.setTag(Constants.FANS_AWARD_TAG.REAL_NAME_AUTH);
            onlyOneAwardEntity.setState(Constants.ONLY_ONE_AWARD_STATE.VALID);
            onlyOneAwardEntity.setAgentNo(agentInfoEntity.getAgentNo());
            onlyOneAwardEntity.setAgentNo1(agentInfoEntity.getAgentNo1());
            onlyOneAwardEntity.setAgentNo2(agentInfoEntity.getAgentNo2());
            onlyOneAwardEntity.setAgentNo3(agentInfoEntity.getAgentNo3());
            onlyOneAwardEntity.setAgentNo4(agentInfoEntity.getAgentNo4());
            onlyOneAwardService.save(onlyOneAwardEntity);
        }
        log.info("该用户fansId：{}领取的待激活奖品为：{}", fansId, JSONUtil.toJsonStr(fansAwardEntity));
        return fansAwardEntity.getFansAwardId();
    }

    /**
     * 自动激活奖品
     */
    public Long autoActivateAward(FansAwardEntity fansAwardEntity, ActivityAwardAndSettingBo activityAwardAndSettingBo, String agentNo) {
        return activateAward(fansAwardEntity, activityAwardAndSettingBo,null, agentNo, null);
    }

    /**
     * 激活奖品
     *
     * @return
     * @agentNo 机构号（用于判断用户归属机构）
     * @agentEmployeeVO 机构客户经理信息（用于核销实物奖品/激活卡券奖品）
     */
    public Long activateAward(FansAwardEntity fansAwardEntity, ActivityAwardAndSettingBo activityAwardAndSettingBo, AgentEmployeeVO agentEmployeeVO, String agentNo, String receiptContent) {
        log.info("用户待激活奖品数据：{}",JSONUtil.toJsonStr(fansAwardEntity));
        if(fansAwardEntity==null){
            throw new BizException("奖品领取记录不存在！");
        }
        Long awardId = fansAwardEntity.getAwardId();
        Integer awardType = fansAwardEntity.getAwardType();

        fansAwardEntity.setActivateTime(new Date());
        if (ObjectUtils.isNotEmpty(agentEmployeeVO)) {
            if (agentEmployeeVO.getFansId() != null) {
                fansAwardEntity.setActivateAgentEmployeeId(agentEmployeeVO.getAgentEmployeeId());
            }
            if (ObjectUtils.isNotEmpty(agentEmployeeVO.getAgentNo())) {
                fansAwardEntity.setActivateAgentNo(agentEmployeeVO.getAgentNo());
                fansAwardEntity.setActivateAgentNo1(agentEmployeeVO.getAgentNo1());
                fansAwardEntity.setActivateAgentNo2(agentEmployeeVO.getAgentNo2());
                fansAwardEntity.setActivateAgentNo3(agentEmployeeVO.getAgentNo3());
                fansAwardEntity.setActivateAgentNo4(agentEmployeeVO.getAgentNo4());
            }
        }
        JSONObject extraJson = new JSONObject();
        String extraStr = fansAwardEntity.getExtraJson();
        if (StringUtils.isNotEmpty(extraStr)){
            extraJson = JSONObject.parseObject(extraStr);
        }else {
            if (ObjectUtils.isNotEmpty(receiptContent)) {
                extraJson.put("receiptContent", receiptContent);
            }
        }
        fansAwardEntity.setExtraJson(JSONUtil.toJsonStr(extraJson));

        JSONObject awardCheckJson = awardSettingService.AwardSettingRule(fansAwardEntity.getFansId(), agentNo, activityAwardAndSettingBo);
        Long redisOutTime = null;
        if(Constants.AWARD.GOODS==awardType){
            // 查询机构分配限制
            if (1 == activityAwardAndSettingBo.getIsAllocation()) {
                if (ObjectUtils.isEmpty(agentEmployeeVO.getAgentNo())) {
                    throw new BizException("绑定机构异常，请检查");
                }
                LambdaQueryWrapper<AwardAgentEntity> gw = AwardAgentEntity.gw().eq(AwardAgentEntity::getAwardId, awardId).eq(AwardAgentEntity::getAwardType, awardType)
                        .eq(AwardAgentEntity::getAgentNo4, agentEmployeeVO.getAgentNo());
                List<AwardAgentEntity> awardAgentList = awardAgentService.list(gw);
                if (ObjectUtils.isEmpty(awardAgentList) || awardAgentList.size() > 1) {
                    throw new BizException("本机构无法核销该奖品");
                }
                AwardAgentEntity awardAgentEntity = awardAgentList.get(0);
                if (awardAgentEntity.getNum() < 1 || awardAgentEntity.getNumConsume() >= awardAgentEntity.getNum()) {
                    throw new BizException("本机构已无库存");
                }
                awardAgentEntity.setNumConsume(awardAgentEntity.getNumConsume() + 1);
                awardAgentService.updateById(awardAgentEntity);
            }

            fansAwardEntity.setState(Constants.FANS_AWARD_STATE.USED);
            fansAwardEntity.setWriteTime(new Date());
            //校验是否回执，如果是添加回执信息，改变回执状态
            awardSettingService.checkIsRecipt(activityAwardAndSettingBo,fansAwardEntity.getExtraJson(),fansAwardEntity);
        }else if(Constants.AWARD.COUPON==awardType) {
            fansAwardEntity.setState(Constants.FANS_AWARD_STATE.UNUSED);
            AwardCouponEntity awardCouponEntity = awardCouponService.getById(fansAwardEntity.getAwardId());
            if (ObjectUtils.isNotEmpty(awardCouponEntity) && ObjectUtils.isNotEmpty(awardCouponEntity.getEndTime())) {
                redisOutTime = awardCouponEntity.getEndTime().getTime() - System.currentTimeMillis();
            }
        }
        send(fansAwardEntity, activityAwardAndSettingBo.getPayAuthId(), true, receiptContent, activityAwardAndSettingBo, null, null, null);

        fansAwardService.updateById(fansAwardEntity);

        // 过期ACTE028其他待激活卡券
        if (ObjectUtils.isNotEmpty(extraJson.getString("templateNo")) && "ACTE028".equals(extraJson.getString("templateNo"))) {
            fansAwardService.disableACTE028Award(fansAwardEntity, extraJson);
        }
        log.info("用户激活后奖品数据：{}",JSONUtil.toJsonStr(fansAwardEntity));

        awardSettingService.updateAwardLimitCache(awardCheckJson, redisOutTime);
        return fansAwardEntity.getFansAwardId();
    }

    /**
     * 校验同主体发券信息是否完善
     * @param fansId
     * @param activityAwardAndSettingBo
     * @return
     */
    public void checkActivitySubject(Long fansId, ActivityAwardAndSettingBo activityAwardAndSettingBo) {
        log.info("校验是否同主体发券,payAuthId：{}", activityAwardAndSettingBo.getPayAuthId());
        if(ObjectUtils.isNotEmpty(activityAwardAndSettingBo.getPayAuthId())){
            PayAuthEntity payAuthEntity = payAuthService.getById(activityAwardAndSettingBo.getPayAuthId());
            if (ObjectUtils.isEmpty(payAuthEntity)) {
                throw new BizException("支付通道异常");
            }
            if(payAuthEntity.getIsCommSubject()==0){
                FansPayEntity fansPayEntity = fansPayService.getOne(FansPayEntity.gw().eq(FansPayEntity::getFansId, fansId).eq(FansPayEntity::getIfCode, payAuthEntity.getIfCode()));
                if(ObjectUtils.isEmpty(fansPayEntity)){
                    log.info("同主体发券,fansId：{},用户未授权，返回小程序码。",fansId);
                    // 查询app秘钥
                    BaseAgentApp agentApp = agentAppService.getAgentApp(activityAwardAndSettingBo.getAppid());
                    // 生成小程序码
                    String qrCode = WxUtil.getUnlimitedQRCode(activityAwardAndSettingBo.getActivityId(), activityAwardAndSettingBo.getAppid(), agentApp.getAppSecret(), activityAwardAndSettingBo.getEndTime().getTime() - System.currentTimeMillis(), isFormalCode);
                    throw new BizException(ApiCodeEnum.LITE_USER_SUBJECT_OFFICIAL_ERROR, qrCode);
                }
            }
        }
    }

    /**
     * 发送卡券激活消息
     */
    public void sendActivateCouponMsg(Long activityId, Long fansId, Long fansAwardId, Long awardId, String activityName, String couponName) {
        //发送消息
        try {
            JSONObject json = new JSONObject();
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
            String format = simpleDateFormat.format(new Date());
            ActivityAppEntity activityAppEntity = activityAppService.getOne(
                    ActivityAppEntity.gw()
                            .eq(ActivityAppEntity::getActivityId, activityId)
                            .eq(ActivityAppEntity::getType, 0)
            );
            FansUserEntity openidByAgentNo = fansUserService.findOpenidByAppIdAndFansId(activityAppEntity.getAppId(), fansId);
            json.put("openid", openidByAgentNo.getOpenId());
            json.put("appid", activityAppEntity.getAppId());
            json.put("thing2", activityName);
            json.put("thing15", couponName);
            json.put("thing5", "已激活");
            json.put("pagepath", "pageUser/myCoupon/viewInfo?flag=0&fansAwardId=" + fansAwardId + "&couponId=" + awardId);
            json.put("time", format);
            log.info("卡券激活推送消息通知，请求参数：{}", JSONUtil.toJsonStr(json));
            // 进行微信公众号消息推送
            officialService.sendTemplateMessage(json, activityAppEntity.getAppId(), officialMenuService.setWxService(activityAppEntity.getAppId()));
        } catch (Exception e) {
            log.info("发送卡券激活消息异常");
            e.printStackTrace();
        }
    }

}
